package org.filecollector.filecontroller.virtualcatalogue.virtualfile;

import junit.framework.TestCase;
import org.apache.commons.lang3.ArrayUtils;
import org.junit.Test;

import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;

public class TestVirtualFile {

    private VirtualFile constructVF() {
        File file;
        try {
            file = Files.createTempFile("111", "").toFile();
            file.deleteOnExit();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        var dao = new VirtualFileDao(file, 111L);
        var dependencies = VirtualFileDependencies.getTest();
        return VirtualFilesFactory.constructSpecialVF(dao, dependencies);
    }

    @Test
    public void TestIsExists() {
        var vf = constructVF();
        TestCase.assertTrue(vf.isExists());
        vf.getDao().innerFile().delete();
        TestCase.assertFalse(vf.isExists());
    }

    @Test
    public void getId() {
        TestCase.assertEquals(Long.valueOf(111L), constructVF().getId());
    }

    @Test
    public void TestSize() {
        String putStr = new String("WHATWHATWHAT");
        var vf = constructVF();
        try (FileWriter fw = new FileWriter(vf.getDao().innerFile())) {
            fw.write(putStr.toCharArray());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        TestCase.assertEquals(vf.size(), Long.valueOf(putStr.length()));
    }

    @Test
    public void TestGetPath() {
        var vf = constructVF();
        TestCase.assertEquals(vf.getPath(), vf.getDao().innerFile().toPath());
    }

    @Test
    public void TestCalculateCheckSum() {
        TestCase.assertEquals(constructVF().calculateCheckSum(), Long.valueOf(0L));
    }

    @Test
    public void TestWriteDirectly() {
        var vf = constructVF();
        char[] exp = {'f', 'u', 'c', 'k'};
        char[] ret = new char[exp.length];
        var data = vf.getDao();
        vf.writeDirectly(exp, false);
        var file = data.innerFile();
        try(FileReader reader = new FileReader(file)) {
            reader.read(ret);
        } catch (Exception e) {
            throw new RuntimeException();
        }
        int i = 0;
        for (var ch : exp) {
            TestCase.assertEquals(ch, ret[i]);
            i++;
        }
        char[] add = {'a', 'd', 'd'};
        char[] exp2 = ArrayUtils.addAll(exp, add);
        char[] ret2 = new char[exp2.length];
        vf.writeDirectly(add, true);
        try(FileReader reader = new FileReader(file)) {
            reader.read(ret2);
        } catch (Exception e) {
            throw new RuntimeException();
        }
        i = 0;
        for (var ch : exp2) {
            TestCase.assertEquals(ch, ret2[i]);
            i++;
        }
    }

    @Test
    public void TestReadDirectly() {
        var vf = constructVF();
        char[] exp = {'f', 'u', 'c', 'k'};
        char[] ret;
        var data = vf.getDao();
        var file = data.innerFile();
        try (FileWriter writer = new FileWriter(file)) {
            writer.write(exp);
        } catch (Exception e) {
            throw new RuntimeException();
        }
        ret = vf.readDirectly(exp.length);
        int i = 0;
        for (var ch : exp) {
            TestCase.assertEquals(ch, ret[i]);
            i++;
        }
    }

    @Test
    public void TestRemove() {
        var vf = constructVF();
        vf.remove();
        TestCase.assertFalse(vf.getDao().innerFile().exists());
    }
}
